#include "syntax_parser.h"
#include "errors_warnings.h"


#include "main_container.h"
extern MainContainer * CompilerData;

// <and_destroy> ~ and destroy  {and}
// <and_destroy> ~ ? {!, -, +, (, LITERAL, null, new, NAME, ;}
void Parser::Parse_AndDestroy(SyntaxTreeNode * parent)
{
#ifdef TRACE
	CompilerData->LogTrace->ReportEntry("Parse_AndDestroy");
#endif

	LexicUnit currentUnit;

#ifdef TRACE
	CompilerData->LogTrace->ReportLine("Getting lexic unit.");
#endif
	// get current lexic unit
	currentUnit = CompilerData->Units->GetLexicUnit(this->CurrentLexicPosition);

	// if current lexic unit is in the select set of {and} 
	if(currentUnit.type == LUTypeKeyword && currentUnit.subtype == KeywordAnd)
	{
		// write type of production in this node
		parent->Production = Gr_AndDestroy__and_destroy;
		
		// process terminal symbol 'and' 
		SyntaxTreeNode * newNode0 = new SyntaxTreeNode();
		parent->Nodes->Add(newNode0);
		newNode0->LexUnitID=this->CurrentLexicPosition;
		newNode0->Production=Gr_Terminal;
		//increase counter
		CurrentLexicPosition++;

		// process terminal symbol 'destroy' 
		currentUnit = CompilerData->Units->GetLexicUnit(this->CurrentLexicPosition);
		if(currentUnit.type == LUTypeKeyword && currentUnit.subtype == KeywordDestroy)
		{
			SyntaxTreeNode * newNode1 = new SyntaxTreeNode();
			parent->Nodes->Add(newNode1);
			newNode1->LexUnitID=this->CurrentLexicPosition;
			newNode1->Production=Gr_Terminal;
			//increase counter
			CurrentLexicPosition++;
		}
		else
		{
			//report syntactic error
			CompilerData->ErrorWarningReport->ReportError(&currentUnit, ERR_SYN_NO_DESTROY_MATCH);
			//increase counter
			CurrentLexicPosition++;
		}
	}
	// if current lexic unit is in the select set of {!, -, +, (, LITERAL, null, new, NAME, ;}
	else if(currentUnit.type == LUTypeOperator && 
		(currentUnit.subtype == OperatorNot || currentUnit.subtype == OperatorSubtraction || currentUnit.subtype == OperatorAddition)
		|| (currentUnit.type == LUTypeSpecialCharacter && (currentUnit.subtype == SpecialCharacterLeftParenthesis || currentUnit.subtype == SpecialCharacterSemicolon))
		|| (currentUnit.type == LUTypeKeyword && (currentUnit.subtype == KeywordNew || currentUnit.subtype == KeywordNull))
		|| (currentUnit.type == LUTypeIdentifier)
		|| (currentUnit.type == LUTypeConstantBool || currentUnit.type == LUTypeConstantFloat || currentUnit.type == LUTypeConstantInteger))
	{
		// this is epsilon part of production
		parent->Production = Gr_AndDestroy__epsilon;
		// new node is not needed
		// there are no symbols on the right side of this production
		// so that all
	}
	else
	{
		// ERROR has been found
		CompilerData->ErrorWarningReport->ReportError(&currentUnit, ERR_SYN_NO_AND_DESTROY_BEGINING);
		// MAKE LOGICAL RECOVERING
	}
#ifdef TRACE
	CompilerData->LogTrace->ReportExit("Parse_AndDestroy");
#endif
}


// <execute_block> ~ execute { <method_body> }  {execute}
// <execute_block> ~ exec { <method_body> }  {exec}
void Parser::Parse_ExecuteBlock(SyntaxTreeNode * parent)
{
#ifdef TRACE
	CompilerData->LogTrace->ReportEntry("Parse_ExecuteBlock");
#endif

	LexicUnit currentUnit;

#ifdef TRACE
	CompilerData->LogTrace->ReportLine("Getting lexic unit.");
#endif	
	// get current lexic unit
	currentUnit = CompilerData->Units->GetLexicUnit(this->CurrentLexicPosition);
	// if current lexic unit is in the select set of {execute}
	if(currentUnit.type == LUTypeKeyword && currentUnit.subtype == KeywordExecute)
	{
		// write type of production in this node
		parent->Production = Gr_ExecuteBlock__execute_spLCBrac_MethodBody_spRCBrac;
		
		// process terminal symbol 'execute' 
		SyntaxTreeNode * newNode0 = new SyntaxTreeNode();
		parent->Nodes->Add(newNode0);
		newNode0->LexUnitID=this->CurrentLexicPosition;
		newNode0->Production=Gr_Terminal;
		//increase counter
		CurrentLexicPosition++;

		// process terminal symbol '{' 
		currentUnit = CompilerData->Units->GetLexicUnit(this->CurrentLexicPosition);
		if(currentUnit.type == LUTypeSpecialCharacter && currentUnit.subtype == SpecialCharacterLeftCurlyBrace)
		{
			SyntaxTreeNode * newNode1 = new SyntaxTreeNode();
			parent->Nodes->Add(newNode1);
			newNode1->LexUnitID=this->CurrentLexicPosition;
			newNode1->Production=Gr_Terminal;
			//increase counter
			CurrentLexicPosition++;
		}
		else
		{
			//report syntactic error
			CompilerData->ErrorWarningReport->ReportError(&currentUnit, ERR_SYN_NO_LEFT_CURLY_BRACE_MATCH);
			//increase counter
			CurrentLexicPosition++;
		}

		// process nonterminal symbol <method_body> 
		SyntaxTreeNode * newNode2 = new SyntaxTreeNode();
		parent->Nodes->Add(newNode2);
		Parse_MethodBody(newNode2);

		// process terminal symbol '}' 
		currentUnit = CompilerData->Units->GetLexicUnit(this->CurrentLexicPosition);
		if(currentUnit.type == LUTypeSpecialCharacter && currentUnit.subtype == SpecialCharacterRightCurlyBrace)
		{
			SyntaxTreeNode * newNode3 = new SyntaxTreeNode();
			parent->Nodes->Add(newNode3);
			newNode3->LexUnitID=this->CurrentLexicPosition;
			newNode3->Production=Gr_Terminal;
			//increase counter
			CurrentLexicPosition++;
		}
		else
		{
			//report syntactic error
			CompilerData->ErrorWarningReport->ReportError(&currentUnit, ERR_SYN_NO_RIGHT_CURLY_BRACE_MATCH);
			//increase counter
			CurrentLexicPosition++;
		}
	}
	// if current lexic unit is in the select set of {exec}
	else if(currentUnit.type == LUTypeKeyword && currentUnit.subtype == KeywordExec)
	{
		// write type of production in this node
		parent->Production = Gr_ExecuteBlock__exec_spLCBrac_MethodBody_spRCBrac;
		
		// process terminal symbol 'exec' 
		SyntaxTreeNode * newNode0 = new SyntaxTreeNode();
		parent->Nodes->Add(newNode0);
		newNode0->LexUnitID=this->CurrentLexicPosition;
		newNode0->Production=Gr_Terminal;
		//increase counter
		CurrentLexicPosition++;

		// process terminal symbol '{' 
		currentUnit = CompilerData->Units->GetLexicUnit(this->CurrentLexicPosition);
		if(currentUnit.type == LUTypeSpecialCharacter && currentUnit.subtype == SpecialCharacterLeftCurlyBrace)
		{
			SyntaxTreeNode * newNode1 = new SyntaxTreeNode();
			parent->Nodes->Add(newNode1);
			newNode1->LexUnitID=this->CurrentLexicPosition;
			newNode1->Production=Gr_Terminal;
			//increase counter
			CurrentLexicPosition++;
		}
		else
		{
			//report syntactic error			
			CompilerData->ErrorWarningReport->ReportError(&currentUnit, ERR_SYN_NO_LEFT_CURLY_BRACE_MATCH);
			//increase counter
			CurrentLexicPosition++;
		}

		// process nonterminal symbol <method_body> 
		SyntaxTreeNode * newNode2 = new SyntaxTreeNode();
		parent->Nodes->Add(newNode2);
		Parse_MethodBody(newNode2);

		// process terminal symbol '}' 
		currentUnit = CompilerData->Units->GetLexicUnit(this->CurrentLexicPosition);
		if(currentUnit.type == LUTypeSpecialCharacter && currentUnit.subtype == SpecialCharacterRightCurlyBrace)
		{
			SyntaxTreeNode * newNode3 = new SyntaxTreeNode();
			parent->Nodes->Add(newNode3);
			newNode3->LexUnitID=this->CurrentLexicPosition;
			newNode3->Production=Gr_Terminal;
			//increase counter
			CurrentLexicPosition++;
		}
		else
		{
			//report syntactic error
			CompilerData->ErrorWarningReport->ReportError(&currentUnit, ERR_SYN_NO_RIGHT_CURLY_BRACE_MATCH);
			//increase counter
			CurrentLexicPosition++;
		}
	}
	else
	{
		// ERROR has been found
		CompilerData->ErrorWarningReport->ReportError(&currentUnit, ERR_SYN_NO_EXECUTE_BLOCK_BEGINING);
		// MAKE LOGICAL RECOVERING
	}
#ifdef TRACE
	CompilerData->LogTrace->ReportExit("Parse_ExecuteBlock");
#endif
}


// <simulation> ~ simulation NAME { <simulation_body> }  {simulation}
void Parser::Parse_Simulation(SyntaxTreeNode * parent)
{
#ifdef TRACE
	CompilerData->LogTrace->ReportEntry("Parse_Simulation");
#endif

	LexicUnit currentUnit;
#ifdef TRACE
	CompilerData->LogTrace->ReportLine("Getting lexic unit.");
#endif
	// get current lexic unit
	currentUnit = CompilerData->Units->GetLexicUnit(this->CurrentLexicPosition);

	// if current lexic unit is in the select set of {simulation}
	if(currentUnit.type == LUTypeKeyword && currentUnit.subtype == KeywordSimulation)
	{
		// write type of production in this node
		parent->Production = Gr_Simulation__simulation_NAME_spLCBrac_SimulationBody_spRCBrac;

		// process terminal symbol 'simulation' 
		SyntaxTreeNode * newNode0 = new SyntaxTreeNode();
		parent->Nodes->Add(newNode0);
		newNode0->LexUnitID=this->CurrentLexicPosition;
		newNode0->Production=Gr_Terminal;
		//increase counter
		CurrentLexicPosition++;

		// process terminal symbol 'NAME' 
		currentUnit = CompilerData->Units->GetLexicUnit(this->CurrentLexicPosition);
		if(currentUnit.type == LUTypeIdentifier)
		{
			SyntaxTreeNode * newNode1 = new SyntaxTreeNode();
			parent->Nodes->Add(newNode1);
			newNode1->LexUnitID=this->CurrentLexicPosition;
			newNode1->Production=Gr_Terminal;
			//increase counter
			CurrentLexicPosition++;
		}
		else
		{
			//report syntactic error
			CompilerData->ErrorWarningReport->ReportError(&currentUnit, ERR_SYN_NO_NAME_MATCH);
			//increase counter
			CurrentLexicPosition++;
		}

		// process terminal symbol '{' 
		currentUnit = CompilerData->Units->GetLexicUnit(this->CurrentLexicPosition);
		if(currentUnit.type == LUTypeSpecialCharacter && currentUnit.subtype == SpecialCharacterLeftCurlyBrace)
		{
			SyntaxTreeNode * newNode2 = new SyntaxTreeNode();
			parent->Nodes->Add(newNode2);
			newNode2->LexUnitID=this->CurrentLexicPosition;
			newNode2->Production=Gr_Terminal;
			//increase counter
			CurrentLexicPosition++;
		}
		else
		{
			//report syntactic error
			CompilerData->ErrorWarningReport->ReportError(&currentUnit, ERR_SYN_NO_LEFT_CURLY_BRACE_MATCH);
			//increase counter
			CurrentLexicPosition++;
		}

		// process nonterminal symbol <simulation_body> 
		SyntaxTreeNode * newNode3 = new SyntaxTreeNode();
		parent->Nodes->Add(newNode3);
		Parse_SimulationBody(newNode3);

		// process terminal symbol '}' 
		currentUnit = CompilerData->Units->GetLexicUnit(this->CurrentLexicPosition);
		if(currentUnit.type == LUTypeSpecialCharacter && currentUnit.subtype == SpecialCharacterRightCurlyBrace)
		{
			SyntaxTreeNode * newNode4 = new SyntaxTreeNode();
			parent->Nodes->Add(newNode4);
			newNode4->LexUnitID=this->CurrentLexicPosition;
			newNode4->Production=Gr_Terminal;
			//increase counter
			CurrentLexicPosition++;
		}
		else
		{
			//report syntactic error
			CompilerData->ErrorWarningReport->ReportError(&currentUnit, ERR_SYN_NO_RIGHT_CURLY_BRACE_MATCH);
			//increase counter
			CurrentLexicPosition++;
		}

	}
	else
	{
		// ERROR has been found
		CompilerData->ErrorWarningReport->ReportError(&currentUnit, ERR_SYN_NO_SIMULATION_BEGINING);
		// MAKE LOGICAL RECOVERING
	}
#ifdef TRACE
	CompilerData->LogTrace->ReportExit("Parse_Simulation");
#endif
}


// <simulation_body> ~ <simulation_stmt> <simulation_body>  {configuration, run, clear, reset}
// <simulation_body> ~ ? {}}
// This production is seen as: <simulation_body> ~ <simulation_stmt> <simulation_stmt><simulation_stmt>...epsilon
void Parser::Parse_SimulationBody(SyntaxTreeNode * parent)
{
#ifdef TRACE
	CompilerData->LogTrace->ReportEntry("Parse_SimulationBody");
#endif

	LexicUnit currentUnit;
	do
	{
		#ifdef TRACE
			CompilerData->LogTrace->ReportLine("Getting lexic unit.");
		#endif
		// get current lexic unit
		currentUnit = CompilerData->Units->GetLexicUnit(this->CurrentLexicPosition);
		// if current lexic unit is in the select set of {configuration, run, clear, reset}
		if(currentUnit.type == LUTypeKeyword && (currentUnit.subtype == KeywordConfiguration || currentUnit.subtype == KeywordRun 
			|| currentUnit.subtype == KeywordClear || currentUnit.subtype == KeywordReset))
		{
			// write type of production in this node
			parent->Production = Gr_SimulationBody__SimulationStmt_SimulationBody;

			// make SimulationStmt node and add child node to a parent node
			SyntaxTreeNode * newNode0 = new SyntaxTreeNode();
			parent->Nodes->Add(newNode0);
			Parse_SimulationStmt(newNode0);
		}
		else if(currentUnit.type == LUTypeSpecialCharacter && currentUnit.subtype == SpecialCharacterRightCurlyBrace)
		{
			// this is epsilon part of production
			parent->Production = Gr_SimulationBody__SimulationStmt_SimulationBody;
			// new node is not needed
			// there are no symbols on the right side of this production
			// so that all
			break;
		}
		else
		{
			// ERROR has been found
			CompilerData->ErrorWarningReport->ReportError(&currentUnit, ERR_SYN_NO_SIMULATION_BODY_BEGINING);
			// MAKE LOGICAL RECOVERING
			this->CurrentLexicPosition++;
			break;
		}
	}
	while(1);
#ifdef TRACE
	CompilerData->LogTrace->ReportExit("Parse_SimulationBody");
#endif
}

// <simulation_stmt> ~ <sim_configuration>  {configuration}
// <simulation_stmt> ~ <sim_run>  {run}
// <simulation_stmt> ~ <sim_clear>  {clear}
// <simulation_stmt> ~ <sim_reset>  {reset}
void Parser::Parse_SimulationStmt(SyntaxTreeNode * parent)
{
#ifdef TRACE
	CompilerData->LogTrace->ReportEntry("Parse_SimulationStmt");
#endif

	LexicUnit currentUnit;
	
#ifdef TRACE
	CompilerData->LogTrace->ReportLine("Getting lexic unit.");
#endif
	// get current lexic unit
	currentUnit = CompilerData->Units->GetLexicUnit(this->CurrentLexicPosition);

	// if current lexic unit is in the select set of {configuration}
	if(currentUnit.type == LUTypeKeyword && currentUnit.subtype == KeywordConfiguration)
	{
		// write type of production in this node
		parent->Production = Gr_SimulationStmt__SimConfiguration;

		// process nonterminal symbol <sim_configuration> 
		SyntaxTreeNode * newNode0 = new SyntaxTreeNode();
		parent->Nodes->Add(newNode0);
		Parse_SimConfiguration(newNode0);

	}
	// if current lexic unit is in the select set of {run}
	else if(currentUnit.type == LUTypeKeyword && currentUnit.subtype == KeywordRun)
	{
		// write type of production in this node
		parent->Production = Gr_SimulationStmt__SimRun;

		// process nonterminal symbol <sim_run> 
		SyntaxTreeNode * newNode0 = new SyntaxTreeNode();
		parent->Nodes->Add(newNode0);
		Parse_SimRun(newNode0);

	}
	// if current lexic unit is in the select set of {clear}
	else if(currentUnit.type == LUTypeKeyword && currentUnit.subtype == KeywordClear)
	{
		// write type of production in this node
		parent->Production = Gr_SimulationStmt__SimClear;

		// process nonterminal symbol <sim_clear> 
		SyntaxTreeNode * newNode0 = new SyntaxTreeNode();
		parent->Nodes->Add(newNode0);
		Parse_SimClear(newNode0);

	}
	// if current lexic unit is in the select set of {reset}
	else if(currentUnit.type == LUTypeKeyword && currentUnit.subtype == KeywordReset)
	{
		// write type of production in this node
		parent->Production = Gr_SimulationStmt__SimReset;

		// process nonterminal symbol <sim_reset> 
		SyntaxTreeNode * newNode0 = new SyntaxTreeNode();
		parent->Nodes->Add(newNode0);
		Parse_SimReset(newNode0);

	}
	else
	{
		// ERROR has been found
		CompilerData->ErrorWarningReport->ReportError(&currentUnit, ERR_SYN_NO_SIMULATION_STMT_BEGINING);
		// MAKE LOGICAL RECOVERING
	}
#ifdef TRACE
	CompilerData->LogTrace->ReportExit("Parse_SimulationStmt");
#endif
}



// <sim_configuration> ~ configuration <name> ( <arguments> ) ;  {configuration}
void Parser::Parse_SimConfiguration(SyntaxTreeNode * parent)
{
#ifdef TRACE
	CompilerData->LogTrace->ReportEntry("Parse_SimConfiguration");
#endif

	LexicUnit currentUnit;
#ifdef TRACE
	CompilerData->LogTrace->ReportLine("Getting lexic unit.");
#endif
	// get current lexic unit
	currentUnit = CompilerData->Units->GetLexicUnit(this->CurrentLexicPosition);

	// if current lexic unit is in the select set of {configuration}
	if(currentUnit.type == LUTypeKeyword && currentUnit.subtype == KeywordConfiguration)
	{
		// write type of production in this node
		parent->Production = Gr_SimConfiguration__configuration_Name_spLPar_Arguments_spRPar_spSemiCol;

		// process terminal symbol 'configuration' 
		SyntaxTreeNode * newNode0 = new SyntaxTreeNode();
		parent->Nodes->Add(newNode0);
		newNode0->LexUnitID=this->CurrentLexicPosition;
		newNode0->Production=Gr_Terminal;
		//increase counter
		CurrentLexicPosition++;

		// process nonterminal symbol <name> 
		SyntaxTreeNode * newNode1 = new SyntaxTreeNode();
		parent->Nodes->Add(newNode1);
		Parse_Name(newNode1);

		// process terminal symbol '(' 
		currentUnit = CompilerData->Units->GetLexicUnit(this->CurrentLexicPosition);
		if(currentUnit.type == LUTypeSpecialCharacter && currentUnit.subtype == SpecialCharacterLeftParenthesis)
		{
			SyntaxTreeNode * newNode2 = new SyntaxTreeNode();
			parent->Nodes->Add(newNode2);
			newNode2->LexUnitID=this->CurrentLexicPosition;
			newNode2->Production=Gr_Terminal;
			//increase counter
			CurrentLexicPosition++;
		}
		else
		{
			//report syntactic error
			CompilerData->ErrorWarningReport->ReportError(&currentUnit, ERR_SYN_NO_LEFT_PARENTHESIS_MATCH);
			//increase counter
			CurrentLexicPosition++;
		}

		// process nonterminal symbol <arguments> 
		SyntaxTreeNode * newNode3 = new SyntaxTreeNode();
		parent->Nodes->Add(newNode3);
		Parse_Arguments(newNode3);

		// process terminal symbol ')' 
		currentUnit = CompilerData->Units->GetLexicUnit(this->CurrentLexicPosition);
		if(currentUnit.type == LUTypeSpecialCharacter && currentUnit.subtype == SpecialCharacterRightParenthesis)
		{
			SyntaxTreeNode * newNode4 = new SyntaxTreeNode();
			parent->Nodes->Add(newNode4);
			newNode4->LexUnitID=this->CurrentLexicPosition;
			newNode4->Production=Gr_Terminal;
			//increase counter
			CurrentLexicPosition++;
		}
		else
		{
			//report syntactic error
			CompilerData->ErrorWarningReport->ReportError(&currentUnit, ERR_SYN_NO_RIGHT_PARENTHESIS_MATCH);
			//increase counter
			CurrentLexicPosition++;
		}

		// process terminal symbol ';' 
		currentUnit = CompilerData->Units->GetLexicUnit(this->CurrentLexicPosition);
		if(currentUnit.type == LUTypeSpecialCharacter && currentUnit.subtype == SpecialCharacterSemicolon)
		{
			SyntaxTreeNode * newNode5 = new SyntaxTreeNode();
			parent->Nodes->Add(newNode5);
			newNode5->LexUnitID=this->CurrentLexicPosition;
			newNode5->Production=Gr_Terminal;
			//increase counter
			CurrentLexicPosition++;
		}
		else
		{
			//report syntactic error
			CompilerData->ErrorWarningReport->ReportError(&currentUnit, ERR_SYN_NO_SEMICOLON_MATCH);
			//increase counter
			CurrentLexicPosition++;
		}

	}
	else
	{
		// ERROR has been found
		CompilerData->ErrorWarningReport->ReportError(&currentUnit, ERR_SYN_NO_SIM_CONFIGURATION_BEGINING);
		// MAKE LOGICAL RECOVERING
	}
#ifdef TRACE
	CompilerData->LogTrace->ReportExit("Parse_SimConfiguration");
#endif
}


// <sim_clear> ~ clear ;  {clear}
void Parser::Parse_SimClear(SyntaxTreeNode * parent)
{
#ifdef TRACE
	CompilerData->LogTrace->ReportEntry("Parse_SimClear");
#endif

	LexicUnit currentUnit;
#ifdef TRACE
	CompilerData->LogTrace->ReportLine("Getting lexic unit.");
#endif
	// get current lexic unit
	currentUnit = CompilerData->Units->GetLexicUnit(this->CurrentLexicPosition);

	// if current lexic unit is in the select set of {clear}
	if(currentUnit.type == LUTypeKeyword && currentUnit.subtype == KeywordClear)
	{
		// write type of production in this node
		parent->Production = Gr_SimClear__clear_spSemiCol;

		// process terminal symbol 'clear' 
		SyntaxTreeNode * newNode0 = new SyntaxTreeNode();
		parent->Nodes->Add(newNode0);
		newNode0->LexUnitID=this->CurrentLexicPosition;
		newNode0->Production=Gr_Terminal;
		//increase counter
		CurrentLexicPosition++;

		// process terminal symbol ';' 
		currentUnit = CompilerData->Units->GetLexicUnit(this->CurrentLexicPosition);
		if(currentUnit.type == LUTypeSpecialCharacter && currentUnit.subtype == SpecialCharacterSemicolon)
		{
			SyntaxTreeNode * newNode1 = new SyntaxTreeNode();
			parent->Nodes->Add(newNode1);
			newNode1->LexUnitID=this->CurrentLexicPosition;
			newNode1->Production=Gr_Terminal;
			//increase counter
			CurrentLexicPosition++;
		}
		else
		{
			//report syntactic error
			CompilerData->ErrorWarningReport->ReportError(&currentUnit, ERR_SYN_NO_SEMICOLON_MATCH);
			//increase counter
			CurrentLexicPosition++;
		}
	}
	else
	{
		// ERROR has been found
		CompilerData->ErrorWarningReport->ReportError(&currentUnit, ERR_SYN_NO_SIM_CLEAR_BEGINING);
		// MAKE LOGICAL RECOVERING
	}
#ifdef TRACE
	CompilerData->LogTrace->ReportExit("Parse_SimClear");
#endif
}


// <sim_reset> ~ reset ;  {reset}
void Parser::Parse_SimReset(SyntaxTreeNode * parent)
{
#ifdef TRACE
	CompilerData->LogTrace->ReportEntry("Parse_SimReset");
#endif
	LexicUnit currentUnit;
#ifdef TRACE
	CompilerData->LogTrace->ReportLine("Getting lexic unit.");
#endif
	// get current lexic unit
	currentUnit = CompilerData->Units->GetLexicUnit(this->CurrentLexicPosition);

	// if current lexic unit is in the select set of {reset}
	if(currentUnit.type == LUTypeKeyword && currentUnit.subtype == KeywordReset)
	{
		// write type of production in this node
		parent->Production = Gr_SimReset__reset_spSemiCol;

		// process terminal symbol 'reset' 
		SyntaxTreeNode * newNode0 = new SyntaxTreeNode();
		parent->Nodes->Add(newNode0);
		newNode0->LexUnitID=this->CurrentLexicPosition;
		newNode0->Production=Gr_Terminal;
		//increase counter
		CurrentLexicPosition++;

		// process terminal symbol ';' 
		currentUnit = CompilerData->Units->GetLexicUnit(this->CurrentLexicPosition);
		if(currentUnit.type == LUTypeSpecialCharacter && currentUnit.subtype == SpecialCharacterSemicolon)
		{
			SyntaxTreeNode * newNode1 = new SyntaxTreeNode();
			parent->Nodes->Add(newNode1);
			newNode1->LexUnitID=this->CurrentLexicPosition;
			newNode1->Production=Gr_Terminal;
			//increase counter
			CurrentLexicPosition++;
		}
		else
		{
			//report syntactic error
			CompilerData->ErrorWarningReport->ReportError(&currentUnit, ERR_SYN_NO_SEMICOLON_MATCH);
			//increase counter
			CurrentLexicPosition++;
		}

	}
	else
	{
		// ERROR has been found
		CompilerData->ErrorWarningReport->ReportError(&currentUnit, ERR_SYN_NO_SIM_RESET_BEGINING);
		// MAKE LOGICAL RECOVERING
	}
#ifdef TRACE
	CompilerData->LogTrace->ReportExit("Parse_SimReset");
#endif
}



// <initialisation> ~ { <initial_values> }  {{}
// <initialisation> ~ ? {:, ^, *, /, %, +, -, <, >, <=, >=, ==, !=, &&, ^^, ||, ,, ;, ), +-, forming, units, simulations, ], NAME, after, every, send, while, until,}}
void Parser::Parse_Initialisation(SyntaxTreeNode * parent)
{
#ifdef TRACE
	CompilerData->LogTrace->ReportEntry("Parse_Initialisation");
#endif

	LexicUnit currentUnit;
#ifdef TRACE
	CompilerData->LogTrace->ReportLine("Getting lexic unit.");
#endif
	// get current lexic unit
	currentUnit = CompilerData->Units->GetLexicUnit(this->CurrentLexicPosition);

	// if current lexic unit is in the select set of {{}
	if(currentUnit.type == LUTypeSpecialCharacter && currentUnit.subtype == SpecialCharacterLeftCurlyBrace)
	{
		// write type of production in this node
		parent->Production = Gr_Initialisation__spLCBrac_InitialValues_spRCBrac;

		// process terminal symbol '{' 
		SyntaxTreeNode * newNode0 = new SyntaxTreeNode();
		parent->Nodes->Add(newNode0);
		newNode0->LexUnitID=this->CurrentLexicPosition;
		newNode0->Production=Gr_Terminal;
		//increase counter
		CurrentLexicPosition++;

		// process nonterminal symbol <initial_value> 
		SyntaxTreeNode * newNode1 = new SyntaxTreeNode();
		parent->Nodes->Add(newNode1);
		Parse_InitialValues(newNode1);

		// process terminal symbol '}' 
		currentUnit = CompilerData->Units->GetLexicUnit(this->CurrentLexicPosition);
		if(currentUnit.type == LUTypeSpecialCharacter && currentUnit.subtype == SpecialCharacterRightCurlyBrace)
		{
			SyntaxTreeNode * newNode2 = new SyntaxTreeNode();
			parent->Nodes->Add(newNode2);
			newNode2->LexUnitID=this->CurrentLexicPosition;
			newNode2->Production=Gr_Terminal;
			//increase counter
			CurrentLexicPosition++;
		}
		else
		{
			//report syntactic error
			CompilerData->ErrorWarningReport->ReportError(&currentUnit, ERR_SYN_NO_RIGHT_CURLY_BRACE_MATCH);
			//increase counter
			CurrentLexicPosition++;
		}
	}
	// if current lexic unit is in the select set of {^, *, /, %, +, -, <, >, <=, >=, ==, !=, &&, ^^, 
	// ||, ,, ;, ), +-, forming, units, simulations, ], NAME, after, every, send, on, while, until}
	else if((currentUnit.type == LUTypeSpecialCharacter && (currentUnit.subtype == SpecialCharacterComma || currentUnit.subtype == SpecialCharacterSemicolon || currentUnit.subtype == SpecialCharacterColon
		|| currentUnit.subtype == SpecialCharacterRightParenthesis || currentUnit.subtype == SpecialCharacterPlusOrMinus ||currentUnit.subtype == SpecialCharacterRightSquareBracket))
		|| (currentUnit.type == LUTypeOperator && (currentUnit.subtype == OperatorExponentiation || currentUnit.subtype == OperatorMultiplication
		|| currentUnit.subtype == OperatorDivision || currentUnit.subtype == OperatorModulus || currentUnit.subtype == OperatorAddition
		|| currentUnit.subtype == OperatorSubtraction || currentUnit.subtype == OperatorLessThan || currentUnit.subtype == OperatorGreaterThan
		|| currentUnit.subtype == OperatorLessThanOrEqualTo || currentUnit.subtype == OperatorGreaterThanEqualTo || currentUnit.subtype == OperatorEqual
		|| currentUnit.subtype == OperatorNotEqual || currentUnit.subtype == OperatorAnd || currentUnit.subtype == OperatorXor
		|| currentUnit.subtype == OperatorOr))
		|| (currentUnit.type == LUTypeKeyword && (currentUnit.subtype == KeywordForming || currentUnit.subtype == KeywordUnits
		|| currentUnit.subtype == KeywordSimulations || currentUnit.subtype == KeywordAfter || currentUnit.subtype == KeywordEvery
		|| currentUnit.subtype == KeywordSend || currentUnit.subtype == KeywordWhile
		|| currentUnit.subtype == KeywordUntil))
		|| currentUnit.type == LUTypeIdentifier)
	{
		// this is epsilon part of production
		parent->Production = Gr_Initialisation__epsilon;
		// new node is not needed
		// there are no symbols on the right side of this production
		// so that all
	}
	else
	{
		// ERROR has been found
		CompilerData->ErrorWarningReport->ReportError(&currentUnit, ERR_SYN_NO_INITIALISATION_BEGINING);
		// MAKE LOGICAL RECOVERING
	}
#ifdef TRACE
	CompilerData->LogTrace->ReportExit("Parse_Initialisation");
#endif
}

// <initial_values> ~ <initial_value> <initial_value_add>  {{, !, -, +, LITERAL, null, new, NAME, (}
// <initial_values> ~ ? {}}
void Parser::Parse_InitialValues(SyntaxTreeNode * parent)
{
#ifdef TRACE
	CompilerData->LogTrace->ReportEntry("Parse_InitialValues");
#endif

	LexicUnit currentUnit;

#ifdef TRACE
	CompilerData->LogTrace->ReportLine("Getting lexic unit.");
#endif	
	// get current lexic unit
	currentUnit = CompilerData->Units->GetLexicUnit(this->CurrentLexicPosition);


	// <initial_values> ~ <initial_value> <initial_value_add>  {{, !, -, +, LITERAL, null, new, NAME, (}
	if(currentUnit.type == LUTypeOperator && (currentUnit.subtype == OperatorNot
		|| currentUnit.subtype == OperatorSubtraction || currentUnit.subtype == OperatorAddition) || (currentUnit.type == LUTypeConstantBool || currentUnit.type == LUTypeConstantFloat || currentUnit.type == LUTypeConstantInteger)
		|| (currentUnit.type == LUTypeKeyword && currentUnit.subtype == KeywordNull)
		|| (currentUnit.type == LUTypeKeyword && currentUnit.subtype == KeywordNew)
		|| (currentUnit.type == LUTypeIdentifier)
		|| (currentUnit.type == LUTypeSpecialCharacter && currentUnit.subtype == SpecialCharacterLeftParenthesis))
	{
		// write type of production in this node
		parent->Production = Gr_InitialValues__InitialValue_InitialValueAdd;

		// process nonterminal symbol <initial_value> 
		SyntaxTreeNode * newNode0 = new SyntaxTreeNode();
		parent->Nodes->Add(newNode0);
		Parse_InitialValue(newNode0);

		// process nonterminal symbol <initial_value_add> 
		SyntaxTreeNode * newNode1 = new SyntaxTreeNode();
		parent->Nodes->Add(newNode1);
		Parse_InitialValueAdd(newNode1);

	}
	// if current lexic unit is in the select set of {}}
	else if(currentUnit.type == LUTypeSpecialCharacter && currentUnit.subtype == SpecialCharacterRightCurlyBrace)
	{
		// this is epsilon part of production
		parent->Production = Gr_InitialValues__epsilon;
		// new node is not needed
		// there are no symbols on the right side of this production
		// so that all
	}
	else
	{
		// ERROR has been found
		CompilerData->ErrorWarningReport->ReportError(&currentUnit, ERR_SYN_NO_INITIAL_VALUES_BEGINING);
		// REPORT ERROR
		// MAKE LOGICAL RECOVERING
	}
#ifdef TRACE
	CompilerData->LogTrace->ReportExit("Parse_InitialValues");
#endif
}


// <initial_value_add> ~ <initial_value_comma> <initial_value_add>  {,}
// <initial_value_add> ~ ? {}}
// This production is seen as: <initial_value_add> ~ <initial_value_comma> <initial_value_comma><initial_value_comma>...epsilon
void Parser::Parse_InitialValueAdd(SyntaxTreeNode * parent)
{
#ifdef TRACE
	CompilerData->LogTrace->ReportEntry("Parse_InitialValueAdd");
#endif

	LexicUnit currentUnit;
	do
	{
		#ifdef TRACE
			CompilerData->LogTrace->ReportLine("Getting lexic unit.");
		#endif
		// get current lexic unit
		currentUnit = CompilerData->Units->GetLexicUnit(this->CurrentLexicPosition);

		// if current lexic unit is in the select set of {,}
		if(currentUnit.type == LUTypeSpecialCharacter && currentUnit.subtype == SpecialCharacterComma)
		{
			// write type of production in this node
			parent->Production = Gr_InitialValueAdd__InitialValueComma_InitialValueAdd;

			// make InitialValueComma node and add child node to a parent node
			SyntaxTreeNode * newNode0 = new SyntaxTreeNode();
			parent->Nodes->Add(newNode0);
			Parse_InitialValueComma(newNode0);
		}
		// if current lexic unit is in the select set of {}}
		else if(currentUnit.type == LUTypeSpecialCharacter && currentUnit.subtype == SpecialCharacterRightCurlyBrace)
		{
			// this is epsilon part of production
			parent->Production = Gr_InitialValueAdd__InitialValueComma_InitialValueAdd;
			// new node is not needed
			// there are no symbols on the right side of this production
			// so that all
			break;
		}
		else
		{
			// ERROR has been found
			CompilerData->ErrorWarningReport->ReportError(&currentUnit, ERR_SYN_NO_INITIAL_VALUE_ADD_BEGINING);
			this->CurrentLexicPosition++;
			break;
	
		}
	}
	while(1);
#ifdef TRACE
	CompilerData->LogTrace->ReportExit("Parse_InitialValueAdd");
#endif
}


// <initial_value> ~ { <initial_values> }  {{}
// <initial_value> ~ <expression>  {!, -, +, LITERAL, null, new, NAME, (}
void Parser::Parse_InitialValue(SyntaxTreeNode * parent)
{
#ifdef TRACE
	CompilerData->LogTrace->ReportEntry("Parse_InitialValue");
#endif
	LexicUnit currentUnit;
#ifdef TRACE
	CompilerData->LogTrace->ReportLine("Getting lexic unit.");
#endif
	// get current lexic unit
	currentUnit = CompilerData->Units->GetLexicUnit(this->CurrentLexicPosition);
	// if current lexic unit is in the select set of {{}
	if(currentUnit.type == LUTypeSpecialCharacter && currentUnit.subtype == SpecialCharacterLeftCurlyBrace)
	{
		// write type of production in this node
		parent->Production = Gr_InitialValue__spLCBrac_InitialValues_spRCBrac;

		// process terminal symbol '{' 
		SyntaxTreeNode * newNode0 = new SyntaxTreeNode();
		parent->Nodes->Add(newNode0);
		newNode0->LexUnitID=this->CurrentLexicPosition;
		newNode0->Production=Gr_Terminal;
		//increase counter
		CurrentLexicPosition++;

		// process nonterminal symbol <initial_values> 
		SyntaxTreeNode * newNode1 = new SyntaxTreeNode();
		parent->Nodes->Add(newNode1);
		Parse_InitialValues(newNode1);

		// process terminal symbol '}' 
		currentUnit = CompilerData->Units->GetLexicUnit(this->CurrentLexicPosition);
		if(currentUnit.type == LUTypeSpecialCharacter && currentUnit.subtype == SpecialCharacterRightCurlyBrace)
		{
			SyntaxTreeNode * newNode2 = new SyntaxTreeNode();
			parent->Nodes->Add(newNode2);
			newNode2->LexUnitID=this->CurrentLexicPosition;
			newNode2->Production=Gr_Terminal;
			//increase counter
			CurrentLexicPosition++;
		}
		else
		{
			//report syntactic error
			CompilerData->ErrorWarningReport->ReportError(&currentUnit, ERR_SYN_NO_RIGHT_CURLY_BRACE_MATCH);
			//increase counter
			CurrentLexicPosition++;
		}

	}
	
	// <initial_value> ~ <expression>  {!, -, +, LITERAL, null, new, NAME, (}
	else if(currentUnit.type == LUTypeOperator && (currentUnit.subtype == OperatorNot
		|| currentUnit.subtype == OperatorSubtraction || currentUnit.subtype == OperatorAddition) || (currentUnit.type == LUTypeConstantBool || currentUnit.type == LUTypeConstantFloat || currentUnit.type == LUTypeConstantInteger)
		|| (currentUnit.type == LUTypeKeyword && currentUnit.subtype == KeywordNull)
		|| (currentUnit.type == LUTypeKeyword && currentUnit.subtype == KeywordNew)
		|| (currentUnit.type == LUTypeIdentifier)
		|| (currentUnit.type == LUTypeSpecialCharacter && currentUnit.subtype == SpecialCharacterLeftParenthesis))
	{
		// write type of production in this node
		parent->Production =Gr_InitialValue__Expression;

		SyntaxTreeNode * newNode = new SyntaxTreeNode();
		parent->Nodes->Add(newNode);
		Parse_Expression(newNode);
	}

	/*
	// if current lexic unit is in the select set of {LITERAL}
	else if(currentUnit.type == LUTypeConstantBool || currentUnit.type == LUTypeConstantFloat || currentUnit.type == LUTypeConstantInteger)
	{
		// write type of production in this node
		parent->Production = Gr_InitialValue__LITERAL;

		// process terminal symbol 'LITERAL' 
		SyntaxTreeNode * newNode0 = new SyntaxTreeNode();
		parent->Nodes->Add(newNode0);
		newNode0->LexUnitID=this->CurrentLexicPosition;
		newNode0->Production=Gr_Terminal;
		//increase counter
		CurrentLexicPosition++;

	}
	// if current lexic unit is in the select set of {null}
	else if(currentUnit.type == LUTypeKeyword && currentUnit.subtype == KeywordNull)
	{
		// write type of production in this node
		parent->Production = Gr_InitialValue__null;

		// process terminal symbol 'null' 
		SyntaxTreeNode * newNode0 = new SyntaxTreeNode();
		parent->Nodes->Add(newNode0);
		newNode0->LexUnitID=this->CurrentLexicPosition;
		newNode0->Production=Gr_Terminal;
		//increase counter
		CurrentLexicPosition++;

	}
	// if current lexic unit is in the select set of {NAME}
	else if(currentUnit.type == LUTypeIdentifier)
	{
		// write type of production in this node
		parent->Production =Gr_InitialValue__Name_spLPar_Arguments_spRPar;

		// process nonterminal symbol <name> 
		SyntaxTreeNode * newNode0 = new SyntaxTreeNode();
		parent->Nodes->Add(newNode0);
		Parse_Name(newNode0);

		// process terminal symbol '(' 
		currentUnit = CompilerData->Units->GetLexicUnit(this->CurrentLexicPosition);
		if(currentUnit.type == LUTypeSpecialCharacter && currentUnit.subtype == SpecialCharacterLeftParenthesis)
		{
			SyntaxTreeNode * newNode1 = new SyntaxTreeNode();
			parent->Nodes->Add(newNode1);
			newNode1->LexUnitID=this->CurrentLexicPosition;
			newNode1->Production=Gr_Terminal;
			//increase counter
			CurrentLexicPosition++;
		}
		else
		{
			//report syntactic error
			CompilerData->ErrorWarningReport->ReportError(&currentUnit, ERR_SYN_NO_LEFT_PARENTHESIS_MATCH);
			//increase counter
			CurrentLexicPosition++;
		}

		// process nonterminal symbol <arguments> 
		SyntaxTreeNode * newNode2 = new SyntaxTreeNode();
		parent->Nodes->Add(newNode2);
		Parse_Arguments(newNode2);

		// process terminal symbol ')' 
		currentUnit = CompilerData->Units->GetLexicUnit(this->CurrentLexicPosition);
		if(currentUnit.type == LUTypeSpecialCharacter && currentUnit.subtype == SpecialCharacterRightParenthesis)
		{
			SyntaxTreeNode * newNode3 = new SyntaxTreeNode();
			parent->Nodes->Add(newNode3);
			newNode3->LexUnitID=this->CurrentLexicPosition;
			newNode3->Production=Gr_Terminal;
			//increase counter
			CurrentLexicPosition++;
		}
		else
		{
			//report syntactic error
			CompilerData->ErrorWarningReport->ReportError(&currentUnit, ERR_SYN_NO_RIGHT_PARENTHESIS_MATCH);
			//increase counter
			CurrentLexicPosition++;
		}


	}
	*/
	
	
	else
	{
		// ERROR has been found
		CompilerData->ErrorWarningReport->ReportError(&currentUnit, ERR_SYN_NO_INITIAL_VALUE_BEGINING);
		// MAKE LOGICAL RECOVERING
	}
#ifdef TRACE
	CompilerData->LogTrace->ReportExit("Parse_InitialValue");
#endif
}


// <initial_value_comma> ~ , <initial_value>  {,}
void Parser::Parse_InitialValueComma(SyntaxTreeNode * parent)
{
#ifdef TRACE
	CompilerData->LogTrace->ReportEntry("Parse_InitialValueComma");
#endif

	LexicUnit currentUnit;
#ifdef TRACE
	CompilerData->LogTrace->ReportLine("Getting lexic unit.");
#endif
	// get current lexic unit
	currentUnit = CompilerData->Units->GetLexicUnit(this->CurrentLexicPosition);

	// if current lexic unit is in the select set of {,}
	if(currentUnit.type == LUTypeSpecialCharacter && currentUnit.subtype == SpecialCharacterComma)
	{
		// write type of production in this node
		parent->Production = Gr_InitialValueComma__spComma_InitialValue;

		// process terminal symbol ',' 
		SyntaxTreeNode * newNode0 = new SyntaxTreeNode();
		parent->Nodes->Add(newNode0);
		newNode0->LexUnitID=this->CurrentLexicPosition;
		newNode0->Production=Gr_Terminal;
		//increase counter
		CurrentLexicPosition++;

		// process nonterminal symbol <initial_value> 
		SyntaxTreeNode * newNode1 = new SyntaxTreeNode();
		parent->Nodes->Add(newNode1);
		Parse_InitialValue(newNode1);

	}
	else
	{
		// ERROR has been found
		CompilerData->ErrorWarningReport->ReportError(&currentUnit, ERR_SYN_NO_INITIAL_VALUE_COMMA_BEGINING);
		// MAKE LOGICAL RECOVERING
	}
#ifdef TRACE
	CompilerData->LogTrace->ReportExit("Parse_InitialValueComma");
#endif
}


//void Parser::Parse_MethodBody(SyntaxTreeNode * parent)
//{
//}
/*
void Parser::Parse_SimRun(SyntaxTreeNode * parent)
{
}
*/
//void Parser::Parse_Parameters(SyntaxTreeNode * parent)
//{
//}
/*
void Parser::Parse_Name(SyntaxTreeNode * parent)
{
}

void Parser::Parse_MethodCall(SyntaxTreeNode * parent)
{
}*/